"""
@author: blake.wang
@file: logger.py
@time: 2025/10/16 11:30
"""
import logging
import os
import sys
import time
import threading
from logging.handlers import RotatingFileHandler
from typing import Optional, List, Any, cast


class Logger:
    """
    全局日志管理器（单例 + 多进程安全）
    """
    _lock = threading.Lock()
    _initialized = False
    logger: Optional[logging.Logger] = None
    _process_id: Optional[int] = None

    @classmethod
    def set_log(cls, flag: bool = True, reserve_num: int = 100):
        """
        初始化日志系统，每个进程只初始化一次
        """
        pid = os.getpid()
        with cls._lock:
            if cls._initialized and cls._process_id == pid:
                cls.logger.info(f"[Logger] 已经初始化 (PID={pid})")
                return

            cls.logger = cls._create_logger(flag)
            cls._initialized = True
            cls._process_id = pid
            cls._delete_old_logs(reserve_num)
            cls.logger.info(f"[Logger] 初始化完成 (PID={pid})")

    @staticmethod
    def _create_logger(flag: bool = True) -> logging.Logger:
        logger = logging.getLogger("System")
        logger.setLevel(logging.DEBUG)
        if logger.handlers:
            return logger

        # 日志目录
        current_path = os.path.dirname(sys.executable) if getattr(sys, 'frozen', False) \
            else os.path.dirname(os.path.abspath(__file__))
        log_dir = os.path.join(current_path, "log")
        os.makedirs(log_dir, exist_ok=True)

        # 每个进程独立日志文件
        log_file = os.path.join(
            log_dir,
            time.strftime("%Y%m%d_%H%M%S") + f"_{os.getpid()}.log"
        )

        # 文件 handler
        file_handler = RotatingFileHandler(
            log_file, mode='a', maxBytes=10 * 1024 * 1024, backupCount=6, encoding='utf-8'
        )
        file_handler.setLevel(logging.INFO)

        # 控制台 handler
        console_handler = logging.StreamHandler() if flag else None
        if console_handler:
            console_handler.setLevel(logging.INFO)

        fmt = '%(asctime)s.%(msecs)03d - [%(levelname)s] - %(filename)s:%(lineno)d - %(funcName)s() - %(message)s'
        formatter = logging.Formatter(fmt=fmt, datefmt='%Y-%m-%d %H:%M:%S')

        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)
        if console_handler:
            console_handler.setFormatter(formatter)
            logger.addHandler(console_handler)

        return logger

    @staticmethod
    def _get_all_log_files(path: str) -> List[str]:
        try:
            if not os.path.exists(path):
                return []
            return sorted(
                [os.path.join(path, f) for f in os.listdir(path)
                 if f.endswith(".log") and os.path.isfile(os.path.join(path, f))],
                reverse=True
            )
        except Exception as e:
            print("get_all_log_files error:", e)
            return []

    @classmethod
    def _delete_old_logs(cls, reserve_num: int):
        current_path = os.path.dirname(sys.executable) if getattr(sys, 'frozen', False) \
            else os.path.dirname(os.path.abspath(__file__))
        log_path = os.path.join(current_path, "log")
        log_files = cls._get_all_log_files(log_path)
        for old_file in log_files[reserve_num:]:
            try:
                os.remove(old_file)
                print(f"[Logger] 删除旧日志: {old_file}")
            except Exception as e:
                print(f"[Logger] 删除日志失败: {old_file}, message: {e}")


# ===== 延迟绑定 log =====
class _LazyLogger:
    """
    延迟绑定 Logger.logger
    """

    def __init__(self):
        self._cache = {}

    def __getattr__(self, name: str) -> Any:
        if Logger.logger is None:
            raise RuntimeError("Logger 未初始化，请先调用 Logger.set_log()")
        if name not in self._cache:
            self._cache[name] = getattr(Logger.logger, name)
        return self._cache[name]


# 外部直接使用 log.info(...)
log = cast(logging.Logger, _LazyLogger())
